/* Copyright (c) 2008 LepomisLab.com, Andrey Turkin
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "NSControl.h"
#include "NSKeyedUnarchiver.h"
#include "NSActionCell.h"
#include "NSWindow.h"

NSControl::NSControl() : NSView(), _cell(NULL), _tag(-1)
{
	disableAutomaticObservation(wxT("value")); // these notifications will be thrown by cell and redirected by us
	disableAutomaticObservation(wxT("objectValue"));
	disableAutomaticObservation(wxT("action"));
	disableAutomaticObservation(wxT("target"));
	disableAutomaticObservation(wxT("argument")); 
	disableAutomaticObservation(wxT("hidden")); 
	disableAutomaticObservation(wxT("enabled")); 
	exposeBinding(wxT("value"));
	exposeBinding(wxT("enabled"));
	exposeBinding(wxT("target"));
	exposeBinding(wxT("hidden"));
}

void NSControl::_setValue(const wxString& key, wxObject *value)
{
	if (key == wxT("value") || key == wxT("objectValue") || key == wxT("action") || 
		key == wxT("target") || key == wxT("argument") || key == wxT("hidden") || key == wxT("enabled"))
	{
		if (_cell)
			_cell->setValue(key, value);
	} else if (key == wxT("tag"))
	{
		wxVariant *v = wxDynamicCast(value, wxVariant);
		wxASSERT(v);
		_tag = v->GetLong();
	} else
		NSView::_setValue(key, value);
}

wxObject* NSControl::_getValue(const wxString& key)
{
	if (key == wxT("value") || key == wxT("objectValue") || key == wxT("action") ||
		key == wxT("target") || key == wxT("argument") || key == wxT("hidden") || key == wxT("enabled"))
	{
		return _cell ? _cell->getValue(key) : NULL;
	} else if (key == wxT("tag"))
	{
		return new wxVariant(_tag);
	} else
		return NSView::_getValue(key);
}

void NSControl::observeValueForKeypath(const wxString &keypath, NSObject* object, void *context)
{
	if (keypath == wxT("value") || keypath == wxT("objectValue") || keypath == wxT("action") || 
		keypath == wxT("target") || keypath == wxT("argument") || keypath == wxT("hidden") || keypath == wxT("enabled"))
	{
		_willValueChangedForKey(keypath);
		_didValueChangedForKey(keypath);
	}
	NSView::observeValueForKeypath(keypath, object, context);
}


void NSControl::initWithUnarchiver(NSKeyedUnarchiver *archiver)
{
	NSView::initWithUnarchiver(archiver);

	wxObject *__cell = archiver->decodeObjectForKey(wxT("NSCell"));
	if (__cell)
	{
		_cell = wxDynamicCast(__cell, NSCell);
		wxASSERT(_cell != NULL);

		_cell->registerObserver(this, wxT("action"));
		_cell->registerObserver(this, wxT("argument"));
		_cell->registerObserver(this, wxT("value"));
		_cell->registerObserver(this, wxT("target"));
		_cell->registerObserver(this, wxT("enabled"));
		_cell->registerObserver(this, wxT("objectValue"));
		_cell->registerObserver(this, wxT("hidden"));

		NSActionCell *cell = wxDynamicCast(_cell, NSActionCell);
		wxASSERT(cell);
		cell->setControlView(this);
	}

	if (archiver->contains(wxT("NSEnabled")))
		archiver->decodeBoolForKey(wxT("NSEnabled"));
	if (archiver->contains(wxT("NSTag")))
		_tag = archiver->decodeIntForKey(wxT("NSTag"));
}

void NSControl::_releaseWidget()
{
	if (_cell)
		_cell->releaseWidget();
}

wxWindow* NSControl::_allocWidget(NSView *parent)
{
	return _cell ? _cell->allocWidget(parent) : NULL;
}

void NSControl::sendClickAction(void)
{
	wxObject *_trgt = getValue(wxT("target"));
	wxObject *_act = getValue(wxT("action"));
	if (_trgt && _act)
	{
		NSObject *target = wxDynamicCast(_trgt, NSObject);
		wxVariant *v = wxDynamicCast(_act, wxVariant);
		wxASSERT(target&&v);
		wxString action(v->GetString());
		if (action.length()>0)
		{
			sendAction(target, action, getValue(wxT("argument")));
			return;
		}
	}
	bindingInvokeAction(wxT("target"), wxT("argument"));
}

void NSControl::setSize(const wxRect& newSize)
{
	NSView::setSize(newSize);
	if (_cell)
		_cell->updateWidget();
}
